About 7359 letters

About 37 minutes

#Qt Theme - A Pure QSS Qt Theme

Source code: https://github.com/hubenchang0515/QtTheme/

Qt Theme Interface Preview

Qt Theme is a pure QSS-based Qt theme project that allows you to easily improve the styling of existing projects.

It supports C++, PyQt5, PyQt6, PySide2, PySide6, and is also published as WebAssembly on GitHub Pages.

#Installation

Here is a demonstration of usage in Python. First, install it:

pip install QtTheme

#Demo

#Native Style and Code

Let Deep Seek randomly generate a simple interface example for me:

deepseek example code

import sys
from PySide6.QtWidgets import *
from PySide6.QtGui import QPixmap
from PySide6.QtCore import Qt, QTimer

class DemoWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt Widget Demo Interface")
        self.setGeometry(100, 100, 800, 600)
        
        # Create central widget and main layout
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        # Add functional sections
        self.create_input_section(main_layout)
        self.create_selection_section(main_layout)
        self.create_display_section(main_layout)
        self.create_progress_section(main_layout)
        
        # Add status bar
        self.statusBar().showMessage("Ready")

        # Initialize progress value
        self.progress_value = 0
        self.update_progress()

    def create_input_section(self, layout):
        group = QGroupBox("Input Controls")
        grid = QGridLayout()

        # Single line text input
        self.line_edit = QLineEdit()
        self.line_edit.setPlaceholderText("Single line text input...")
        grid.addWidget(QLabel("Single Line Text:"), 0, 0)
        grid.addWidget(self.line_edit, 0, 1)

        # Multi-line text input
        self.text_edit = QTextEdit()
        self.text_edit.setPlaceholderText("Multi-line text input...")
        grid.addWidget(QLabel("Multi-line Text:"), 1, 0)
        grid.addWidget(self.text_edit, 1, 1)

        # Number input
        self.spin_box = QSpinBox()
        self.spin_box.setRange(0, 100)
        grid.addWidget(QLabel("Number Input:"), 2, 0)
        grid.addWidget(self.spin_box, 2, 1)

        group.setLayout(grid)
        layout.addWidget(group)

    def create_selection_section(self, layout):
        group = QGroupBox("Selection Controls")
        hbox = QHBoxLayout()

        # Checkboxes
        vbox = QVBoxLayout()
        self.check1 = QCheckBox("Option 1")
        self.check2 = QCheckBox("Option 2")
        vbox.addWidget(self.check1)
        vbox.addWidget(self.check2)
        hbox.addLayout(vbox)

        # Radio buttons
        vbox = QVBoxLayout()
        self.radio1 = QRadioButton("Radio 1")
        self.radio2 = QRadioButton("Radio 2")
        self.radio1.setChecked(True)
        vbox.addWidget(self.radio1)
        vbox.addWidget(self.radio2)
        hbox.addLayout(vbox)

        # Combo box
        self.combo = QComboBox()
        self.combo.addItems(["Option A", "Option B", "Option C"])
        hbox.addWidget(self.combo)

        group.setLayout(hbox)
        layout.addWidget(group)

    def create_display_section(self, layout):
        group = QGroupBox("Display Controls")
        hbox = QHBoxLayout()

        # Label
        self.label = QLabel("This is a label")
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setStyleSheet("border: 1px solid gray; padding: 10px;")
        hbox.addWidget(self.label)

        # Image display
        pixmap = QPixmap(100, 50)
        pixmap.fill(Qt.blue)
        image_label = QLabel()
        image_label.setPixmap(pixmap)
        hbox.addWidget(image_label)

        # List widget
        self.list_widget = QListWidget()
        self.list_widget.addItems(["Item 1", "Item 2", "Item 3"])
        hbox.addWidget(self.list_widget)

        group.setLayout(hbox)
        layout.addWidget(group)

    def create_progress_section(self, layout):
        group = QGroupBox("Progress Controls")
        vbox = QVBoxLayout()

        # Progress bar
        self.progress_bar = QProgressBar()
        self.progress_bar.setValue(0)
        vbox.addWidget(self.progress_bar)

        # Slider
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, 100)
        self.slider.valueChanged.connect(self.on_slider_changed)
        vbox.addWidget(self.slider)

        # Control buttons
        btn_layout = QHBoxLayout()
        self.start_btn = QPushButton("Start Progress")
        self.start_btn.clicked.connect(self.start_progress)
        self.reset_btn = QPushButton("Reset")
        self.reset_btn.clicked.connect(self.reset_progress)
        btn_layout.addWidget(self.start_btn)
        btn_layout.addWidget(self.reset_btn)

        vbox.addLayout(btn_layout)
        group.setLayout(vbox)
        layout.addWidget(group)

    def on_slider_changed(self, value):
        self.progress_bar.setValue(value)
        self.statusBar().showMessage(f"Slider Value: {value}")

    def start_progress(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_progress)
        self.timer.start(100)

    def update_progress(self):
        self.progress_value += 1
        if self.progress_value > 100:
            self.timer.stop()
            return
        self.progress_bar.setValue(self.progress_value)
        self.slider.setValue(self.progress_value)

    def reset_progress(self):
        self.progress_value = 0
        self.progress_bar.setValue(0)
        self.slider.setValue(0)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = DemoWindow()
    window.show()
    sys.exit(app.exec())

Run it and see:

Native interface style

#Setting Global Style

Import QtTheme and apply the style:

import QtTheme.PySide6 as QtTheme

class DemoWindow(QMainWindow):
    def __init__(self):
        # omitted...

        # Set global stylesheet
        self.setStyleSheet(QtTheme.getThemeStyle('Flat', 'Dark', 'Blue', 'Pink'))

Global dark style

#Setting Colors

Finally, set colors on widgets as needed via QWidget.setProperty:

    def create_progress_section(self, layout):
        # omitted...

        # Set colors for buttons
        self.start_btn.setProperty("Color", "Primary")
        self.reset_btn.setProperty("Color", "Danger")

After setting colors

#Exporting Resources

You can also skip installing QtTheme and export resources via the online page, then include them in your project using RCC:

pyside6-rcc -o resource.py QtTheme.qrc

Just modify the import style, keep other code unchanged:

from PySide6.QtCore import QFile
import resource  # import the generated resource.py

class DemoWindow(QMainWindow):
    def __init__(self):
        # omitted...

        qss = QFile(":/QtTheme/theme/Flat/Dark/Blue/Pink.qss")
        qss.open(QFile.OpenModeFlag.ReadOnly)
        self.setStyleSheet(qss.readAll().data().decode())

Updated: 5/15/2025

Author: PlanC

Created: 5/15/2025